package com.jin.mqtt;


import android.text.TextUtils;
import android.util.Log;

import org.eclipse.paho.client.mqttv3.IMqttActionListener;
import org.eclipse.paho.client.mqttv3.IMqttDeliveryToken;
import org.eclipse.paho.client.mqttv3.IMqttToken;
import org.eclipse.paho.client.mqttv3.MqttAsyncClient;
import org.eclipse.paho.client.mqttv3.MqttCallback;
import org.eclipse.paho.client.mqttv3.MqttConnectOptions;
import org.eclipse.paho.client.mqttv3.MqttException;
import org.eclipse.paho.client.mqttv3.MqttMessage;
import org.eclipse.paho.client.mqttv3.persist.MemoryPersistence;

import java.util.Arrays;
import java.util.Map;
import java.util.concurrent.atomic.AtomicBoolean;

public enum MQTTManager implements MqttCallback {

    INSTANCE;

    private static final String TAG = MQTTManager.class.getSimpleName();

    private static final AtomicBoolean isConnecting = new AtomicBoolean(false);
    private static MqttAsyncClient mqttClient;


    public synchronized void connect(String clientId, String url, String username, String password) {
        Log.d(TAG, "connect: "+url+":"+clientId);
        if (isConnecting.get()) {
            Log.d(TAG, "connect: 连接中，跳过重复请求...");
            return;
        }

        isConnecting.set(true);
        if (mqttClient != null && mqttClient.isConnected()) {
            return;
        }

        try {
            mqttClient = new MqttAsyncClient(url, clientId, new MemoryPersistence());

            mqttClient.setCallback(this);

            MqttConnectOptions options = new MqttConnectOptions();

            // 配置连接选项
            options.setUserName(username); // 设置用户名
            options.setPassword(password.toCharArray()); // 设置密码
            options.setAutomaticReconnect(true);  // 让 MQTT 自动尝试重新连接
            options.setCleanSession(false);       // 维持会话，避免重连后订阅丢失
            options.setKeepAliveInterval(10);     // 心跳间隔，单位：秒
            options.setConnectionTimeout(10);     // 连接超时时间，单位：秒

            // 启用 TLS/SSL
//            options.setSocketFactory(SSLContext.getDefault().getSocketFactory());

            mqttClient.connect(options, null, new IMqttActionListener() {
                @Override
                public void onSuccess(IMqttToken asyncActionToken) {
                    Log.d(TAG, "MQTT 连接成功: " + mqttClient.isConnected() + ":" + asyncActionToken.toString());
                    isConnecting.set(false);
                    if (mOnMqttStatusListener != null) {
                        mOnMqttStatusListener.onConnectStatus(true, asyncActionToken.toString());
                    }
                }

                @Override
                public void onFailure(IMqttToken asyncActionToken, Throwable exception) {
                    Log.d(TAG, "MQTT 连接失败: " + exception.getMessage());
                    isConnecting.set(false);
                    if (mOnMqttStatusListener != null) {
                        mOnMqttStatusListener.onConnectStatus(false, exception.toString());
                    }
                }
            });
        } catch (MqttException e) {
            isConnecting.set(false);
            Log.e(TAG, "MQTT 连接异常: ", e);
        }
    }

    public void disconnect() {
        try {
            mqttClient.disconnect();
            if (mOnMqttStatusListener != null) {
                mOnMqttStatusListener.onDisconnect();
            }
        } catch (MqttException e) {
            Log.e(TAG, "disconnect: ", e);
        }
    }

    public void reportMicroInfo(String payload){
        publish("/microneedle/report/info", payload);
    }

    /**
     * 上报开始治疗
     *
     * @param serialNumber
     */
    public void publishStartCure(String serialNumber) {
        String payload = "{\"serialNum\":\"" + serialNumber + "\"}";
        publish("/treatmentdevice/report/start", payload);
    }

    /**
     * 上报发数已用完
     *
     * @param serialNumber
     */
    public void publishNumberRunOut(String serialNumber) {
        String payload = "{\"serialNum\":\"" + serialNumber + "\"}";
        publish("/treatmentdevice/report/useup", payload);
    }

    /**
     * 查询微针信息
     *
     * @param serialNumber
     */
    public void queryNeedleInfo(String serialNumber) {
        String payload = "{\"serialNum\":\"" + serialNumber + "\"}";
        publish("/microneedle/report/queryinfo", payload);
    }

    public void queryUpgrade(String serialNumber, String version) {
        String payload = "{\"serialNum\":\"" + serialNumber + "\",\"version\":\"" + version + "\"}";
        publish("/microneedle/report/upgrade", payload);
    }

    /**
     * 标准发布
     *
     * @param topic
     * @param message
     */
    public void publish(String topic, String message) {
        Log.d(TAG, "发布主题: "+topic+": "+message);
        if (TextUtils.isEmpty(topic) || TextUtils.isEmpty(message)) {
            return;
        }
        if (mqttClient == null) {
            return;
        }
        if (message==null || message.getBytes()==null){
            return;
        }
        try {
            MqttMessage mqttMessage = new MqttMessage(message.getBytes());
            mqttMessage.setQos(1);
            mqttClient.publish(topic, mqttMessage);
            if (mOnMqttStatusListener != null) {
                mOnMqttStatusListener.onPublishStatus("发布主题成功", topic);
            }
        } catch (MqttException e) {
            if (mOnMqttStatusListener != null) {
                mOnMqttStatusListener.onPublishStatus("发布主题失败," + e.getMessage(), topic);
            }
        }
    }

    /**
     * 批量发布
     *
     * @param messages
     */
    private void publishMultipleMessages(Map<String, String> messages) {
        for (Map.Entry<String, String> entry : messages.entrySet()) {
            String topic = entry.getKey();
            String message = entry.getValue();
            publish(topic, message);
        }
    }

    /**
     * 带回复发布
     *
     * @param topic
     * @param message
     */
    private void publishMessageWithCallback(String topic, String message) {
        try {
            MqttMessage mqttMessage = new MqttMessage(message.getBytes());
            mqttMessage.setQos(1);

            mqttClient.publish(topic, mqttMessage, null, new IMqttActionListener() {
                @Override
                public void onSuccess(IMqttToken asyncActionToken) {
                    Log.d("MQTT", "发布成功 - 主题：" + topic + " 内容：" + message);
                }

                @Override
                public void onFailure(IMqttToken asyncActionToken, Throwable exception) {
                    Log.e("MQTT", "发布失败：" + exception.getMessage());
                }
            });
        } catch (MqttException e) {
            e.printStackTrace();
        }
    }

    /**
     * 上报应答
     *
     * @param treatmentId
     */
    public void subscribeTreatmentIdAck(String treatmentId) {
        String serialNumber = treatmentId.replace("\0", "");
        if (!TextUtils.isEmpty(serialNumber)) {
            subscribe("/treatmentdevice/ack/" + serialNumber);
        }
    }

    public void subscribeMicroAck(String id) {
        subscribe("/microneedle/ack/" + id);
    }


    /**
     * 订阅主题
     *
     * @param topic
     */
    public void subscribe(String topic) {
        Log.d(TAG, "订阅主题: "+topic);
        if (mqttClient == null) return;
        try {
            mqttClient.subscribe(topic, 0);
            if (mOnMqttStatusListener != null) {
                mOnMqttStatusListener.onSubscribeStatus(true, topic);
            }
        } catch (MqttException e) {
            mOnMqttStatusListener.onSubscribeStatus(false, topic);
        }
    }

    /**
     * 批量订阅主题
     * <p>
     * String[] topics = {"topic1", "topic2", "topic3", "topic4"};
     * <p>
     * int[] qosLevels = {1, 1, 1, 1}; // 每个主题对应的 QoS 级别
     *
     * @param topics
     */
    private void subscribeTopics(String[] topics, int[] qosLevels) {
        try {
            mqttClient.subscribe(topics, qosLevels, null, new IMqttActionListener() {
                @Override
                public void onSuccess(IMqttToken asyncActionToken) {
                    Log.d("MQTT", "批量订阅成功：" + Arrays.toString(topics));
                }

                @Override
                public void onFailure(IMqttToken asyncActionToken, Throwable exception) {
                    Log.e("MQTT", "批量订阅失败：" + exception.getMessage());
                }
            });
        } catch (MqttException e) {
            e.printStackTrace();
        }
    }


    @Override
    public void connectionLost(Throwable cause) {
        if (mOnMqttStatusListener != null) {
            mOnMqttStatusListener.onConnectionLost(cause.toString());
        }
    }

    @Override
    public void messageArrived(String topic, MqttMessage message) throws Exception {
        if (mOnMqttStatusListener != null) {
            mOnMqttStatusListener.onMessageArrived(topic, message);
        }
    }

    @Override
    public void deliveryComplete(IMqttDeliveryToken token) {
        if (mOnMqttStatusListener != null) {
            mOnMqttStatusListener.onDeliveryComplete(token.toString());
        }
    }


    public interface OnMqttStatusListener {
        void onConnectStatus(boolean status, String token);

        void onDisconnect();

        void onMessageArrived(String topic, MqttMessage message);

        void onDeliveryComplete(String token);

        void onConnectionLost(String cause);

        void onSubscribeStatus(boolean status, String topic);

        void onPublishStatus(String status, String topic);
    }

    public OnMqttStatusListener mOnMqttStatusListener;

    public void setOnMqttStatusListener(OnMqttStatusListener listener) {
        mOnMqttStatusListener = listener;
    }
}